package com.javabloger.orm.common;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.sql.*;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.ResultSetDynaClass;

public class ORMappingTools {
	
	private static final String ObjectColumnName="ObjectColumnName";
	private static final String TableName="TableName";
	private static final String CopyABeanToMap="CopyABeanToMap";
	
	private static ConcurrentHashMap<String,  Object> cache= new ConcurrentHashMap<String, Object> ();
	
	 
	@SuppressWarnings("unchecked")
	public    List<String> getObjectColumnName(Object objTable) {
		String cacheKey=ObjectColumnName+objTable.getClass().toString();
		
		if (cache.get(cacheKey) !=null){
			List<String> list=(List<String>) cache.get(cacheKey) ;
			return list ;
		}
		else{
			Field fields[]=objTable.getClass().getDeclaredFields();
			List<String> list = new ArrayList<String> ();
		
			for (int i=0;i<fields.length;i++){
 				if (fields[i].getAnnotation(ColumnMapping.class)!=null){
 					if (fields[i].getAnnotation(ColumnMapping.class).classPropertiesName().equals(fields[i].getName())) 
 						list.add( fields[i].getAnnotation(ColumnMapping.class).columnName()  );
 				}
 				else{
 					list.add(fields[i].getName() );
 				}
				
			}
			cache.put(cacheKey, list);
			return list;
		}
	}
	
	public    String getTableNameForClass(Class<?> objTable) {
 
		String table = "";
		String cacheKey=TableName+objTable.toString();
		
		if (cache.get(cacheKey) !=null){
			return (String) cache.get(cacheKey) ;
		}
		else{
			if (objTable.getAnnotation(TableMapping.class) == null) {
				table = objTable. getSimpleName();
				}
			else {
				table = objTable.getAnnotation(TableMapping.class).tableName();
			}
			cache.put(cacheKey, table);
			return table;
		}
	}
	
	
 
	public    String getTableNameForObject(Object objTable) {
		String table = "";
		String cacheKey=TableName+objTable.toString();
		
		if (cache.get(cacheKey) !=null){
			return (String) cache.get(cacheKey) ;
		}
		else{
			if (objTable.getClass().getAnnotation(TableMapping.class) == null) {
				table = objTable .getClass().getSimpleName();
			} else {
				table = objTable.getClass().getAnnotation(TableMapping.class).tableName();
			}
			cache.put(cacheKey, table);
			return table;
		}
	}

	 
		public    List<?> toBeanList (  ResultSet rs ,Class<?> clazz1 ){
				 List<Object> list = new ArrayList<Object> ();
				 try{
					 ResultSetDynaClass rsDynaClass = new ResultSetDynaClass(rs);  
					 Iterator<?> itr = rsDynaClass.iterator();
	                 ResultSetMetaData  metaData=  rs.getMetaData();
	                 while (itr.hasNext() ) {
	                	 Object paraObject=clazz1.newInstance();
	                	 Field  Fields[] =paraObject.getClass().getDeclaredFields();
	                	 DynaBean dBean = (DynaBean) itr.next();
	                
	             for (int k=0;k<metaData.getColumnCount(); k++){
		                for (int i = 0; i < Fields.length ; i++) {
		                ColumnMapping columnMapping=Fields[i].getAnnotation(ColumnMapping.class) ;
	                    Object value =null;
	                    if (columnMapping!=null){
	                         if (columnMapping.columnName().equals( rs.getMetaData().getColumnName(k+1 )) ){
	                         value =dBean.get( columnMapping.columnName());
	                         String setMethodName = "set" + Fields[i].getName().substring(0,1).toUpperCase()+Fields[i].getName().substring(1) ;       
//                           System.out.println( setMethodName );
	                         Method setMethod = paraObject.getClass().getMethod(setMethodName, new Class[]{ Fields[i].getType() }); 
                             if (value!=null){  setMethod.invoke(paraObject,  value  );   }
                         }
                     }
                     else{
                         if (Fields[i].getName().equals( rs.getMetaData().getColumnName(k+1 )) ){
	                         value =dBean.get(Fields[i].getName() );
	                         String setMethodName = "set" + Fields[i].getName().substring(0,1).toUpperCase()+Fields[i].getName().substring(1) ;       
	                         Method setMethod = paraObject.getClass().getMethod(setMethodName, new Class[]{ Fields[i].getType() }); 
	                         if (value!=null){  setMethod.invoke(paraObject,  value  );   }
                         	}
                     	  }
		               }
                     }
	             list.add( paraObject);
           } 
           }
           catch (Exception e) {
                  e.printStackTrace();
           }
				return list; 
    }
 
	
		public    Object toBean (  ResultSet rs ,Class<?> clazz1 ) throws  Exception{
 
			Object paraObject=null;
			 try{
				 paraObject=clazz1.newInstance();
				 ResultSetDynaClass rsDynaClass = new ResultSetDynaClass(rs);   Iterator<?> itr = rsDynaClass.iterator();
                 ResultSetMetaData  metaData=  rs.getMetaData();
                 if (itr.hasNext() ) {
               	 
               	 Field  Fields[] =paraObject.getClass().getDeclaredFields();
               	 DynaBean dBean = (DynaBean) itr.next();
               
            for (int k=0;k<metaData.getColumnCount(); k++){
	                	for (int i = 0; i < Fields.length ; i++) {
	               ColumnMapping columnMapping=Fields[i].getAnnotation(ColumnMapping.class) ;
                   Object value =null;
                   if (columnMapping!=null){
                        if (columnMapping.columnName().equals( rs.getMetaData().getColumnName(k+1 )) ){
                        value =dBean.get( columnMapping.columnName());
                        String setMethodName = "set" + Fields[i].getName().substring(0,1).toUpperCase()+Fields[i].getName().substring(1) ;       
                        Method setMethod = paraObject.getClass().getMethod(setMethodName, new Class[]{ Fields[i].getType() }); 
                        setMethod.invoke(paraObject,  value   );  
                    }
                }
                else{
                    if (Fields[i].getName().equals( rs.getMetaData().getColumnName(k+1 )) ){
                        value =dBean.get(Fields[i].getName() );
                        String setMethodName = "set" + Fields[i].getName().substring(0,1).toUpperCase()+Fields[i].getName().substring(1) ;       
                        Method setMethod = paraObject.getClass().getMethod(setMethodName, new Class[]{ Fields[i].getType() }); 
                        setMethod.invoke(paraObject,  value  );  
                    	}
                	  }
	               }
                }
            } 
      }
      catch (Exception e) {
             e.printStackTrace();
      	}
			return paraObject; 
		}
		
		
		
		@SuppressWarnings("unchecked")
		public    Map<String, Object> resultToMap(ResultSet rs) throws Exception    {
					 Map map = new TreeMap ();
					 ResultSetDynaClass rsDynaClass = new ResultSetDynaClass(rs);   
					 Iterator<?> itr = rsDynaClass.iterator();
					
					 if (itr.hasNext() ) {
		            	 DynaBean dBean = (DynaBean) itr.next();
		            	 for (int k=0;k<dBean.getDynaClass().getDynaProperties().length; k++){
		            		 	String name=dBean.getDynaClass().getDynaProperties()[k] .getName() ;
		            		 	map.put(name, dBean.get(name));
		            	 		}
		            	  } 
					return map;     
				}
		
		
	
	 @SuppressWarnings("unchecked")
		public  synchronized  Map<String, Object> copyABeanToMap(Object object) throws Exception    {     
//				String cacheKey=CopyABeanToMap+object.toString();
//				if (cache.get(cacheKey) !=null){
//					System.out.println("get cache .....");
//					return  (Map<String, Object>) cache.get(cacheKey) ;
//				}
//				else{
					System.out.println("get Collections .....");
//					 Map map = Collections.synchronizedMap(new HashMap());
					ConcurrentHashMap  map =new ConcurrentHashMap ();
//					 Map<String, Object> map = new HashMap<String, Object>  ();
					 Class<? extends Object> classType = object.getClass() ;        
					 Field fields[] = classType.getDeclaredFields();       
					 for(int i = 0; i < fields.length; i++)        {           
						 Field field = fields[i];           
						 String fieldName = field.getName();   
						 String getMethodName =null;
							if (fields[i].getAnnotation(ColumnMapping.class)!=null){
								 fieldName =fields[i].getAnnotation(ColumnMapping.class).columnName();    
								 String firstLetter = fields[i].getName().substring(0, 1).toUpperCase();            
								 getMethodName = "get" + firstLetter + fields[i].getName().substring(1);   
								 Method getMethod = classType.getMethod(getMethodName, new Class[]{});
								 Object value = getMethod.invoke(object, new Object[]{});     
								 map.put(fieldName  , value+"" );
							}
						else{
								 fieldName = field.getName();    
								 String firstLetter = fieldName.substring(0, 1).toUpperCase();           
								 getMethodName = "get" + firstLetter + fieldName.substring(1);      
								 Method getMethod = classType.getMethod(getMethodName, new Class[]{});
								 Object value = getMethod.invoke(object, new Object[]{});     
								 map.put(fieldName  , value+"" );
							}
						 }        
					 return map;   
				}
	 	}
	 
//	 }

 
